#ifndef TRAFFIC_JAM_CARS_HPP
#define TRAFFIC_JAM_CARS_HPP

#include <iostream>
#include <stdexcept>
#include "direction.hpp"
#include "to_string.hpp"
#include "pthreadwrapper.hpp"

namespace jam {

typedef uint64_t car_id_t;
typedef void* car_logic_t(void*);

template<direction_t dir, car_logic_t logic>
class Car {
 public:
  typedef Car<dir, logic> car_t;
  typedef void *runnable_t(void *);
  Car(car_id_t id) : id(id) { };
  ~Car() {
    pthread_cancel(thread);
  }
  void emit() {
    int rtv = thread::create<logic>(thread);
    std::cout << to_string(*this) << " ";
    if (rtv != 0) {
      throw std::runtime_error("Cannot create thread.");
    }
  }
  const static direction_t source = dir;
  const static direction_t destination = opposite<dir>::value;
  const car_id_t id;
  pthread_t thread;
};

template<direction_t dir, car_logic_t logic>
std::string to_string(Car<dir, logic> &car) {
  return std::string("Car ") + std::to_string(car.id);
};

}
#endif //TRAFFIC_JAM_CARS_HPP
